Welcome to pandas!

4.4 匹配范围

1、长度匹配

前面是单个元素的元字符,但都只能表示一个字符,以下是长度匹配

匹配模式 注释
{n} 只匹配n次,n是一个非负整数
{n,} 至少匹配n次,n是一个非负整数
{n,m} 至少匹配n次,最多匹配m次,m、n均是非负整数,m大于n
* 匹配前面的子表达式零次或多次,等价于{0,}
+ 匹配前面的子表达式1次以上,等价于{1,}
匹配前面的子表达式0次或1次,等价于{0,1}

import re

text= "小张34-小明16-欧阳一大明45-小曾32"

t=re.compile( "\d{1,}" )

t1=re.compile( "\d+" )

p=t.findall(text)

p1=t1.findall(text)

print (p)

print (p1)

返回:

['34', '16', '45', '32']

['34', '16', '45', '32']


2、边界匹配

正则表达式中的边界匹配是指单词边界和首尾边界,边界匹配是匹配的位置

匹配模式 注释
\b 匹配空字符串,但只在单词开始或结尾的位置
\B 匹配空字符串,但不能在单词开始或结尾
\A 指定匹配必须出现在字符串的开头(忽略re.M选项)
\Z 指定匹配必须出现在字符串的结尾(忽略re.M选项)
^ 匹配字符串开始的位置,设置re.M后,支持多行
$ 匹配字符串结尾的位置,设置re.M后,支持多行

3、分组匹配(常规分组)

分组,就是将正则表达式字符串中的被括号引用的部份为整体,匹配完成后,分组的内容可以被获取,并可以在之后用\number转义序列进行再次匹配,在python中,分组为普通分组与命名分组。

如果有多个分组,但只需获取某个分组的数据,使用findall()也可以,但如果匹配结果为re.match对象时,在获取数据时更方便,可能使用re.match对象的group()函数或者切片方式完成对分组数据的提取。


import re

text= "python20,pandas21,excel22"

t1=re.findall( "[A-Za-z]+\d+" ,text)

t2=re.findall( "([A-Za-z]+)(\d+)" ,text)

t3=re.findall( "(([A-Za-z]+)(\d+))" ,text)

print (t1)

print (t2)

print (t3)

print ("_____")

print (t2[0])

print (t3[0])

返回:

['python20', 'pandas21', 'excel22']

[('python', '20'), ('pandas', '21'), ('excel', '22')]

[('python20', 'python', '20'), ('pandas21', 'pandas', '21'), ('excel22', 'excel', '22')]

_____

('python', '20')

('python20', 'python', '20')


4、分组匹配(命名分组)

命名分组是python正则表达式中一种特殊的分组方式,它可以给分组改一个名称,从而在引用、获取分组数据时可以不用序号方式,而用名称来表示,命名分组很有用,因为允许你使用容易记住的名称,而不必记住数字。

分组命名格式为:在分组的左括号后面加?p<:名称>:,注意p字母是大写的,然后后面是正常的正则表达式字符串编写。


import re

text= "python20,pandas21,excel22"

t=re.finditer( "((?P<:name>:[A-Za-z]+)(?P<:score>:\d+))" ,text)

for m in t:

print (m.group( "name" ))

print (m.group( "score" ))

返回:

python

20

pandas

21

excel

22


5、分组匹配(命名分组)

分组的优点很多,除前面的re.match对象中获取分组数据的方法外,也可以在编写正则表达式字符串时再次引用,还可以使用sub()函数做替换引用。


import re

text= "我们欢欢喜喜的来到公园,蹦蹦跳跳的,结果伤伤心心的走了"

t=re.finditer(r "([一-龥])\1([一-龥])\2" ,text)

print (t)

for m in t:

print (m.group())

返回:

<:callable_iterator object at 0x000001D0FEC57280>:

欢欢喜喜

蹦蹦跳跳

伤伤心心


6、分组在替换处理中的引用

除了正则表达式中引用分组之外,也可以在替换函数中使用,有以下三种引用方式:

(1)第一种引用的方式为\1、\2、\3、

(2)第二种引用的方式为\g<:1>:、\<:2>:、\<:3>:、

(2)第三种引用的方式为\g<:name1>:、\g<: name2>:、\ g<: name3>:、


import re

text= "89Bob100李小萌9王小花120Lucas85小曾"

t=re.findall( "(\d+)(\D+)" ,text)

s=re.sub( "(\d+)(\D+)",r"\2:\1、" ,text)

s1=re.sub( "(\d+)(\D+)" ,r "\g<:2>::\g<:1>:," ,text) #使用这种较好

print (t)

print (s)

print (s1)

返回:

[('89', 'Bob'), ('100', '李小萌'), ('9', '王小花'), ('120', 'Lucas'), ('85', '小曾')]

Bob:89、李小萌:100、王小花:9、Lucas:120、小曾:85、

Bob:89,李小萌:100,王小花:9,Lucas:120,小曾:85,


7、非捕获分组匹配

什么是非捕获分组匹配,就是具有分组匹配的功能,但并不对捕获到的分组内容进行存储。 在分组左括号加在?:即可,表示(?:……)匹配括号内的任何数据不会捕获储存,也不能被引用。


import re

text= "北京234上海32青岛56北京43上海97成都45"

t=re.findall( "(?:北京|上海)\d+" ,text)

t1=re.findall( "(北京|上海)\d+" ,text)

t2=re.findall( "北京|上海\d+" ,text)

print (t)

print (t1)

print (t2)

返回:

['北京234', '上海32', '北京43', '上海97']

['北京', '上海', '北京', '上海']

['北京', '上海32', '北京', '上海97']